home *** CD-ROM | disk | FTP | other *** search
/ POINT Software Programming / PPROG1.ISO / pascal / swag / textfile.swg / 0030_Shared TextFiles.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1993-11-26  |  21.1 KB  |  469 lines

  1. {
  2. From: LEE LEFLER
  3. Subj: Shared textfiles
  4.  
  5.  Want to do some reading of LARGE textfiles on a network.
  6.  How can I open a textfile for reading in
  7.  (readonly+denywrite) mode ?
  8.  
  9.   Some say that Text files can't be shared ?!?!?
  10.  
  11.       Sure they can, but it takes a little special work to do it.  I use
  12. the following unit to share the nodelist.  I don't know who originally wrote it
  13. so I hope it's OK to post.  It's going to need a little cleaning up since the
  14. message readers are going to wrap it, but I don't want to modify it so you guys
  15. will have to handle that when you export it.
  16. }
  17.  
  18. Unit TxtShare;
  19.  
  20. {$F+}
  21.  
  22. { This UNIT implements a TEXT file device driver to access TEXT files with a }
  23. { user specified network access mode (see DOS Technical Reference for DOS }
  24. { function 3Dh).  This can be accomplished for non-TEXT files by setting the }
  25. { standard global variable "FileMode" (part of the System unit) to the desired
  26. }
  27. { value, and then calling the appropriate open function. This is not supported
  28. }
  29. { for TEXT files in Turbo Pascal v4.0. }
  30.  
  31. { To open a Text file with a user specified access mode, place a call to the }
  32. { procedure AssignText to associate a filename with the text file variable. }
  33. { Next, set the standard global variable FileMode with the desired DOS access }
  34. { mode value.  RESET, REWRITE, and APPEND will now use the access mode }
  35. { assigned to the FileMode variable when opening the file. }
  36.  
  37. { By default, no EOF marker is written to text files that have been "assigned"
  38. }
  39. { using this unit's routines.  If you require a ^Z at the end of any file }
  40. { opened for output, set the global variable WriteTextEofChar to TRUE before }
  41. { closing the file. }
  42.  
  43. Interface
  44.  
  45. Uses Dos;
  46.  
  47. Var
  48.    WriteTextEofChar : Boolean;
  49.  
  50. Procedure AssignText(Var F : Text; FileName : String);
  51.  
  52. Implementation
  53.  
  54. {$R-,S-}
  55.  
  56. Var
  57.    ReadText_Addr  : Pointer;
  58.    WriteText_Addr : Pointer;
  59.    SeekText_Addr  : Pointer;
  60.    DoNothing_Addr : Pointer;
  61.    CloseText_Addr : Pointer;
  62.  
  63. Function ReadText(Var F : TextRec) : Word;
  64. Begin
  65.    Inline(
  66.      $1E/                   {       push     ds          ;Save data segment
  67. value}
  68.      $C5/$76/$06/           {       lds      si,[bp+6]   ;Address the file var
  69. structure}
  70.      $AD/                   {       lodsw                ;Pick up file handle}
  71.      $89/$C3/               {       mov      bx,ax       ; ... and store in bx}
  72.      $46/                   {       inc      si          ;Skip past the Mode
  73. field}
  74.      $46/                   {       inc      si          ; ... and address the
  75. BufSize field}
  76.      $AD/                   {       lodsw                ;Pick up BufSize (# of
  77. bytes to read)}
  78.      $89/$C1/               {       mov      cx,ax       ; ... and store in cx}
  79.      $81/$C6/$06/$00/       {       add      si,6        ;Address the BufPtr
  80. field}
  81.      $AD/                   {       lodsw                ;Pick up Offset part
  82. of the pointer}
  83.      $89/$C2/               {       mov      dx,ax       ; ... and store in dx}
  84.      $AD/                   {       lodsw                ;Pick up Segment part
  85. of the pointer}
  86.      $8E/$D8/               {       mov      ds,ax       ; ... and store in ds}
  87.      $B4/$3F/               {       mov      ah,$3F      ;DOS Read a
  88. File/Device function}
  89.      $CD/$21/               {       int      $21         ;Call DOS}
  90.      $72/$0F/               {       jc       Error       ;Error if Carry Flag
  91. set}
  92.      $50/                   {       push     ax          ;Save # of bytes
  93. actually read}
  94.      $31/$C0/               {       xor      ax,ax       ;Clear ax to zero}
  95.      $C4/$7E/$06/           {       les      di,[bp+6]   ;Address the file var
  96. structure}
  97.      $81/$C7/$08/$00/       {       add      di,8        ;Address the BufPos
  98. field}
  99.      $AB/                   {       stosw                ;Store 0 in the BufPos
  100. field}
  101.      $58/                   {       pop      ax          ;Retrieve bytes
  102. actually read}
  103.      $AB/                   {       stosw                ; ... and store in
  104. BufEnd field}
  105.      $31/$C0/               {       xor      ax,ax       ;Return 0 ==> no
  106. errors}
  107.      $1F/                   {Error: pop      ds          ;Restore ds value}
  108.      $89/$46/$FE);          {       mov      [bp-2],ax   ;Store returned value}
  109. End {ReadText};
  110.  
  111. Function WriteText(Var F : TextRec) : Word;
  112. Begin
  113.    Inline(
  114.      $1E/                   {       push     ds          ;Save value of data
  115. seg register}
  116.      $C5/$76/$06/           {       lds      si,[bp+6]   ;DS:SI points to
  117. TextRec structure}
  118.      $AD/                   {       lodsw                ;Pick up file handle}
  119.      $89/$C3/               {       mov      bx,ax       ; ... and store in BX}
  120.      $81/$C6/$06/$00/       {       add      si,6        ;DS:SI points to
  121. BufPos field}
  122.      $AD/                   {       lodsw                ;Pick up # of bytes to
  123. write}
  124.      $89/$C1/               {       mov      cx,ax       ; ... and store in CX}
  125.      $46/                   {       inc      si}
  126.      $46/                   {       inc      si          ;DS:SI points to
  127. BufPtr field}
  128.      $AD/                   {       lodsw                ;Pick up offset part
  129. of buffer addr.}
  130.      $89/$C2/               {       mov      dx,ax       ; ... and store in DX}
  131.      $AD/                   {       lodsw                ;Pick up segment part
  132. of buffer addr.}
  133.      $8E/$D8/               {       mov      ds,ax       ; ... and store in DS}
  134.      $B4/$40/               {       mov      ah,$40      ;DOS write file/device
  135. function}
  136.      $CD/$21/               {       int      $21         ;Call DOS}
  137.      $72/$0B/               {       jc       Error       ;Error if Carry Flag
  138. is set on return}
  139.      $31/$C0/               {       xor      ax,ax       ;Clear AX to zero}
  140.      $C4/$7E/$06/           {       les      di,[bp+6]   ;ES:DI points to
  141. TextRec structure}
  142.      $81/$C7/$08/$00/       {       add      di,8        ;ES:DI points to
  143. BufPos field}
  144.      $AB/                   {       stosw                ;Reset BufPos to zero}
  145.      $AB/                   {       stosw                ;Reset BufEnd to zero}
  146.      $1F/                   {Error: pop      ds          ;Restore data seg
  147. register}
  148.      $89/$46/$FE);          {       mov      [bp-2],ax   ;Store function
  149. result}
  150. End {WriteText};
  151.  
  152. Function DoNothing(Var F : TextRec) : Word;
  153. Begin
  154.    Inline(
  155.      $C7/$46/$FE/$00/$00);    {        mov    word [bp-2],0}
  156. End {DoNothing};
  157.  
  158. Function SeekEofText(Var F : TextRec) : Word;
  159. Begin
  160.    Inline(
  161.      $1E/                     {        push     ds                   ;Save Data
  162. Seg register}
  163.      $C4/$7E/$06/             {        les      di,[bp+6]            ;ES:DI
  164. points to the TextRec}
  165.      $26/$8B/$1D/             {    es: mov word bx,[di]              ;File
  166. handle into BX}
  167.      $31/$C9/                 {        xor      cx,cx                ;CX:DX =
  168. Offset for Seek function}
  169.      $89/$CA/                 {        mov      dx,cx                ;With AL=2
  170. and CX:DX=0, will seek eof}
  171.      $B8/$02/$42/             {        mov      ax,$4202}
  172.      $CD/$21/                 {        int      $21                  ;DX:AX
  173. should now contain filesize}
  174.      $72/$7B/                 {        jc       Error}
  175.      $2D/$80/$00/             {        sub      ax,128
  176. ;Reposition to read the last 128 bytes of}
  177.      $81/$DA/$00/$00/         {        sbb      dx,0                 ;the file
  178. (or as much as we can)}
  179.      $79/$04/                 {        jns      NonNeg               ;If less
  180. than 128 chars in file}
  181.      $31/$C0/                 {        xor      ax,ax                ;  then
  182. just read from beginning}
  183.      $89/$C2/                 {        mov      dx,ax}
  184.      $89/$D1/                 {NonNeg: mov      cx,dx                ;Set up
  185. for Seek function}
  186.      $89/$C2/                 {        mov      dx,ax                ;CX:DX =
  187. Absolute position to seek}
  188.      $26/$89/$55/$20/         {    es: mov word [di+32],dx           ;Save in
  189. UserData field for later}
  190.      $26/$89/$4D/$22/         {    es: mov word [di+34],cx}
  191.      $26/$8B/$1D/             {    es: mov word bx,[di]              ;File
  192. handle in BX}
  193.      $B8/$00/$42/             {        mov      ax,$4200             ;Dos seek
  194. (absolute) function}
  195.      $CD/$21/                 {        int      $21}
  196.      $72/$58/                 {        jc       Error}
  197.      $06/                     {        push     es                   ;Set up
  198. for call to read by pushing}
  199.      $57/                     {        push     di                   ;TextRec
  200. address onto stack}
  201.      $FF/$1E/>READTEXT_ADDR/  {        call far [>ReadText_Addr]     ;Read the
  202. file}
  203.      $09/$C0/                 {        or       ax,ax                ;Any
  204. errors?}
  205.      $75/$4E/                 {        jnz      Error}
  206.      $C5/$76/$06/             {        lds      si,[bp+6]            ;Use DS:SI
  207. as TextRec ptr}
  208.      $8B/$4C/$0A/             {        mov word cx,[si+10]           ;CX = #
  209. bytes read}
  210.      $E3/$44/                 {        jcxz     Done                 ;If 0
  211. bytes read, then we're done}
  212.      $8B/$44/$0C/             {        mov word ax,[si+12]           ;BufPtr
  213. offset}
  214.      $89/$C7/                 {        mov      di,ax                ;ES:DI
  215. will point at the buffer of data}
  216.      $4F/                     {        dec      di                   ;  that
  217. was just read in}
  218.      $01/$CF/                 {        add      di,cx}
  219.      $8B/$44/$0E/             {        mov word ax,[si+14]}
  220.      $8E/$C0/                 {        mov      es,ax}
  221.      $B0/$1A/                 {        mov      al,$1A}
  222.      $FD/                     {        std}
  223.      $F2/$AE/                 {  repnz scasb                         ;Search
  224. buffer for a ^Z}
  225.      $FC/                     {        cld}
  226.      $75/$2F/                 {        jnz      Done                 ;If no ^Z
  227. found, then we're done}
  228.      $C4/$7E/$06/             {        les      di,[bp+6]            ;Back to
  229. using ES:DI for TextRec}
  230.      $1F/                     {        pop      ds                   ;Point DS
  231. back at global variable segment}
  232.      $1E/                     {        push     ds                   ;But push
  233. back for final pop}
  234.      $89/$C8/                 {        mov      ax,cx                ;ax=offset
  235. in buffer at which ^Z was found}
  236.      $26/$8B/$55/$20/         {    es: mov word dx,[di+32]           ;Retrieve
  237. saved file ptr pos.}
  238.      $26/$8B/$4D/$22/         {    es: mov word cx,[di+34]}
  239.      $01/$C2/                 {        add      dx,ax                ;Add in
  240. offset of ^Z}
  241.      $81/$D1/$00/$00/         {        adc      cx,0}
  242.      $26/$8B/$1D/             {    es: mov word bx,[di]              ;file
  243. handle back in BX}
  244.      $B8/$00/$42/             {        mov      ax,$4200             ;Again
  245. with the Seek function}
  246.      $CD/$21/                 {        int      $21
  247. ;Reposition file pointer to ^Z char}
  248.      $72/$12/                 {        jc       Error}
  249.      $26/$C7/$44/$08/$00/$00/ {    es: mov word [si+8],0             ;BufPos=0
  250. (write 0 bytes to truncate ...}
  251.      $06/                     {        push     es                   ; ... the
  252. file at the ^Z)}
  253.      $57/                     {        push     di                   ;Setup for
  254. call to write routine}
  255.      $FF/$1E/>WRITETEXT_ADDR/ {        call far [>WriteText_Addr]}
  256.      $09/$C0/                 {        or       ax,ax                ;Any
  257. errors}
  258.      $75/$02/                 {        jnz      Error}
  259.      $31/$C0/                 {Done:   xor      ax,ax                ;Return 0
  260. if no errors}
  261.      $1F/                     {Error:  pop      ds}
  262.      $89/$46/$FE);            {        mov      [bp-2],ax}
  263. End {SeekEofText};
  264.  
  265. Function CloseText(Var F : TextRec) : Word;
  266. Begin
  267.    Inline(
  268.      $1E/                           {         push     ds
  269. ;Must preserve DS for return}
  270.      $C4/$7E/$06/                   {         les      di,[bp+6]
  271. ;ES:DI is our ptr to the TextRec}
  272.      $26/$8B/$44/$02/               {     es: mov      ax,[si+2]
  273. ;Magic Number into AX}
  274.      $3D/>FMOUTPUT/                 {         cmp word ax,>fmOutput
  275. ;File opened with Rewrite or Append?}
  276.      $75/$2D/                       {         jnz      SkipEof
  277. ;No, skip ^Z stuff}
  278.      $80/$3E/>WRITETEXTEOFCHAR/$01/ {         cmp byte [>WriteTextEofChar],1
  279. ;Use ^Z to mark end of file?}
  280.      $75/$26/                       {         jnz      SkipEof
  281. ;No, skip ^Z stuff}
  282.      $26/$8B/$45/$0C/               {     es: mov word ax,[di+12]
  283. ;Get address of output buffer}
  284.      $26/$8B/$5D/$0E/               {     es: mov word bx,[di+14]}
  285.      $89/$C7/                       {         mov      di,ax}
  286.      $8E/$C3/                       {         mov      es,bx
  287. ;ES:DI points to buffer now}
  288.      $B8/$1A/$00/                   {         mov      ax,$1A}
  289.      $AB/                           {         stosw
  290. ;Put a ^Z into the buffer}
  291.      $C4/$7E/$06/                   {         les      di,[bp+6]
  292. ;Point ES:DI back at the TextRec}
  293.      $26/$C7/$45/$08/$01/$00/       {     es: mov word [di+8],1
  294. ;Set BufPos to show 1 char to write}
  295.      $06/                           {         push     es
  296. ;Put TextRec Address onto stack}
  297.      $57/                           {         push     di}
  298.      $FF/$1E/>WRITETEXT_ADDR/       {         call far [>WriteText_Addr]
  299. ;Call Write routine to write the ^Z}
  300.      $09/$C0/                       {         or       ax,ax
  301. ;Any problems with the write?}
  302.      $75/$1D/                       {         jnz      Error
  303. ;Yes, exit with error code in AX}
  304.      $C4/$7E/$06/                   {         les      di,[bp+6]
  305. ;ES:DI probably trashed in call}
  306.                                     {SkipEof:}
  307.      $26/$8B/$1D/                   {     es: mov      bx,[di]
  308. ;File handle in BX}
  309.      $B8/$00/$3E/                   {         mov      ax,$3E00
  310. ;Dos Close function}
  311.      $CD/$21/                       {         int      $21
  312. ;Close the file}
  313.      $72/$10/                       {         jc       Error
  314. ;If error, exit with code in AX}
  315.      $31/$C0/                       {         xor      ax,ax}
  316.      $26/$89/$45/$08/               {     es: mov word [di+8],ax
  317. ;Stuff zeros in BufPos and BufEnd}
  318.      $26/$89/$45/$0A/               {     es: mov word [di+10],ax}
  319.      $26/$C7/$45/$02/>FMCLOSED/     {     es: mov word [di+2],>fmClosed
  320. ;Reset the magic number}
  321.      $1F/                           {Error:   pop      ds}
  322.      $89/$46/$FE);                  {         mov      [bp-2],ax
  323. ;Store function result}
  324. End {CloseText};
  325.  
  326. Function OpenText(Var F : TextRec) : Word;
  327. Begin
  328.    Inline(
  329.      $1E/                       {         push      ds                  ;Save
  330. DS register}
  331.      $C4/$7E/$06/               {         les       di,[bp+6]           ;ES:DI
  332. is pointer to the TextRec structure}
  333.      $B4/$3D/                   {Start:   mov       ah,$3D              ;DOS
  334. open a file/device function}
  335.      $26/$81/$7D/$02/>FMOUTPUT/ {     es: cmp word  [di+2],>fmOutput    ;Open
  336. for Rewrite?}
  337.      $75/$02/                   {         jnz       OpenIt              ;No,
  338. skip next line}
  339.      $B4/$3C/                   {         mov       ah,$3C              ;DOS
  340. create new/truncate old file}
  341.      $A0/>FILEMODE/             {OpenIt:  mov       al,[>FileMode]      ;Put
  342. user specified access mode in AL}
  343.      $B9/$00/$00/               {         mov       cx,0                ;File
  344. attribute (nothing special) in CX}
  345.      $8C/$C3/                   {         mov       bx,es}
  346.      $8E/$DB/                   {         mov       ds,bx}
  347.      $89/$FA/                   {         mov       dx,di}
  348.      $81/$C2/$30/$00/           {         add       dx,48               ;DS:DX
  349. points to asciiz filename}
  350.      $CD/$21/                   {         int       $21                 ;Open
  351. the file}
  352.      $1F/                       {         pop       ds
  353. ;Restore DS to segment with global vars}
  354.      $1E/                       {         push      ds                  ; ...
  355. and save back on stack for later}
  356.      $73/$15/                   {         jnc       OpenOk              ;If no
  357. errors, continue}
  358.      $3D/$02/$00/               {         cmp       ax,2                ;File
  359. not found?}
  360.      $75/$69/                   {         jnz       Error               ;No,
  361. exit with error code in ax}
  362.      $26/$81/$7D/$02/>FMINOUT/  {     es: cmp word  [di+2],>fmInOut     ;Opened
  363. for Append?}
  364.      $75/$61/                   {         jnz       Error               ;No,
  365. exit with error code in ax}
  366.      $26/$C7/$45/$02/>FMOUTPUT/ {     es: mov word  [di+2],>fmOutput    ;No
  367. existing file to append ...}
  368.      $EB/$C9/                   {         jmp short Start               ; ...
  369. so try again with Rewrite}
  370.      $AB/                       {OpenOk:  stosw                         ;Store
  371. file handle (in AX) into TextRec}
  372.      $BE/>CLOSETEXT_ADDR/       {         mov       si,>CloseText_Addr  ;DS:SI
  373. points at addr. of CloseText fn.}
  374.      $81/$C7/$1A/$00/           {         add       di,26               ;ES:DI
  375. points to CloseFunc field}
  376.      $B9/$02/$00/               {         mov       cx,2                ;Double
  377. word address to move}
  378.      $F2/$A5/                   {     rep movsw                         ;Store
  379. address into CloseFunc field}
  380.      $C4/$7E/$06/               {         les       di,[bp+6]           ;ES:DI
  381. back to pointing at TextRec}
  382.      $26/$81/$7D/$02/>FMINOUT/  {     es: cmp word  [di+2],>fmInOut     ;Opened
  383. with Append?}
  384.      $75/$13/                   {         jnz       NoSeek              ;No,
  385. skip the search for ^Z}
  386.      $06/                       {         push      es                  ;Set up
  387. stack for call to SeekEofText}
  388.      $57/                       {         push      di                  ;Addr
  389. of TextRec goes on the stack}
  390.      $FF/$1E/>SEEKTEXT_ADDR/    {         call far  [>SeekText_Addr]    ;Get
  391. rid of any ^Z at end of file}
  392.      $09/$C0/                   {         or        ax,ax               ;Any
  393. errors?}
  394.      $75/$37/                   {         jnz       Error               ;Yes,
  395. exit with error code in AX}
  396.      $C4/$7E/$06/               {         les       di,[bp+6]
  397. ;Restore ptr to TextRec trashed in call}
  398.      $26/$C7/$45/$02/>FMOUTPUT/ {     es: mov word  [di+2],>fmOutput    ;Reset
  399. TextRec mode to show output only}
  400.                                 {NoSeek:}
  401.      $26/$C7/$45/$08/$00/$00/   {     es: mov word  [di+8],0            ;Set
  402. BufPos to 0}
  403.      $26/$C7/$45/$0A/$00/$00/   {     es: mov word  [di+10],0           ;Set
  404. BufEnd to 0}
  405.      $26/$81/$7D/$02/>FMINPUT/  {     es: cmp word  [di+2],>fmInput     ;Opened
  406. with reset?}
  407.      $74/$05/                   {         jz        InFunc              ;Yes,
  408. set pointers accordingly}
  409.      $BE/>WRITETEXT_ADDR/       {         mov       si,>WriteText_Addr  ;DS:SI
  410. --> Address of WriteText func.}
  411.      $EB/$03/                   {         jmp short SetFunc             ;Go set
  412. TextRec function pointers}
  413.      $BE/>READTEXT_ADDR/        {InFunc:  mov       si,>ReadText_Addr   ;DS:SI
  414. --> Address of ReadText func.}
  415.      $81/$C7/$14/$00/           {SetFunc: add       di,20               ;ES:DI
  416. --> InOutFunc field}
  417.      $B9/$02/$00/               {         mov       cx,2                ;Moving
  418. a double word}
  419.      $51/                       {         push      cx                  ;Save
  420. this count for later}
  421.      $F2/$A5/                   {     rep movsw                         ;Store
  422. address of I/O routine}
  423.      $BE/>DONOTHING_ADDR/       {         mov       si,>DoNothing_Addr  ;DS:SI
  424. --> Address of DoNothing func.}
  425.      $59/                       {         pop       cx                  ;ES:DI
  426. --> FlushFunc field - move 2 words}
  427.      $F2/$A5/                   {     rep movsw                         ;Store
  428. address of flush routine}
  429.      $31/$C0/                   {         xor       ax,ax               ;No
  430. errors, return a 0 to caller}
  431.      $1F/                       {Error:   pop       ds
  432. ;Restore DS register}
  433.      $89/$46/$FE);              {         mov       [bp-2],ax           ;Store
  434. function result}
  435. End {OpenText};
  436.  
  437. Procedure AssignText(Var F : Text; FileName : String);
  438. Var
  439.    I : Integer;
  440. Begin
  441.    With TextRec(F) do begin               { Initialize textrec record         }
  442.       Handle   := $FFFF;                  { Set file handle to junk           }
  443.       Mode     := fmClosed;               { Indicate the file is not yet open }
  444.       BufSize  := SizeOf(Buffer);         { Set size of default buffer (128)  }
  445.       BufPtr   := @Buffer;                { Set up pointer to default buffer  }
  446.       OpenFunc := @OpenText;              { Set up pointer to OPEN function   }
  447.       For I := 1 to Length(FileName) do   { Set up asciiz filename            }
  448.          Name[I-1] := FileName[I];
  449.       Name[Length(FileName)] := Chr(0);
  450.    End {with};
  451. End {AssignText};
  452.  
  453. Begin
  454.    { Initialize global variable to suppress writing ^Z at the end of any     }
  455.    { text file opened with Append or Rewrite.                                }
  456.    WriteTextEofChar := FALSE;
  457.  
  458.    { Initialize internally used Address variables (pointers)                 }
  459.    ReadText_Addr    := Addr(ReadText);
  460.    WriteText_Addr   := Addr(WriteText);
  461.    SeekText_Addr    := Addr(SeekEofText);
  462.    DoNothing_Addr   := Addr(DoNothing);
  463.    CloseText_Addr   := Addr(CloseText);
  464. End {Unit TxtShare}.
  465.  
  466. {$F-}
  467.  
  468. {end}
  469.